import {
  requestDefaultConfig,
  instanceDefaultConfig
} from "../config.js"

import mergeConfig from "../utils/mergeConfig.js"

import defaultRequest from "./request.js"

import InterceptorManager from './InterceptorManager.js'

class Http {
  // 默认的配置
  defaults = {
    ...instanceDefaultConfig
  }

  constructor(config) {
    this.defaults = config || {};
    // 创建 request 和 responese 的拦截器的钩子函数
    this.interceptors = {
      request: new InterceptorManager(),
      responese: new InterceptorManager()
    }
  }

  /**
   * 核心的请求方法
   * @param {Object} config
   */
  request(config) {

    debugger

    // 处理入参
    // 允许两种请求方式
    // 1. http({}).then()
    // 2. http(url , {}).then()
    if (typeof config === 'string') {
      // 说明这是第二种
      config = arguments[1] || {};
      // 第一个参数就是请求的地址
      config.url = arguments[0];
    } else {
      config = config || {};
    }

    // 第二步 处理请求的配置数据
    config = mergeConfig(this.defaults, config);

    // 第三步 处理请求的方式
    if (config.method) {
      // 全部转换成大写
      config.method = config.method.toLocaleUpperCase();
    } else {
      config.method = 'GET';
    }

    // 处理定义的请求和返回拦截器
    // 对于拦截器的处理方式 是通过队列的方式进行处理的
    // 定义一个默认的队列数组
    let chain = [defaultRequest, undefined];
    const promise = Promise.resolve(config)
    // 如果请求之前定义了拦截器 那么就将定义的拦截器放到队列的前面
    this.interceptors.request.forEach(interceptor => {
      chain.unshift(interceptor.fulfilled, interceptor.rejected)
    })

    // 如果定义了responese拦截器 那么就将定义的拦截器放到队列的后面
    this.interceptors.responese.forEach(interceptor => {
      chain.push(interceptor.fulfilled, interceptor.rejected)
    })

    // 按照chain数组中函数的顺序一步一步处理
    while (chain.length) {
      promise = promise.then(chain.shift(), chain.shift())
    }

    return promise;
  }

  /**
   * 获取当前请求的uri
   * @param {Object} config
   */
  getUri(config) {}

  /**
   * 获取当前请求的uri
   * @param {Object} config
   */
  get(url, config) {}

  /**
   * 获取当前请求的uri
   * @param {Object} config
   */
  post(url, data, config) {}
}


export default Http
